﻿using System;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using MediaBot.Entities;
using MediaBot.Library;
using RakutenCrawler.ConfigClass;
using RakutenCrawler.Repository;
using log4net;

namespace RakutenCrawler.PageProcessors
{
    public class ProductCategoriesPageProcessor:PageProcessor
    {
        private static bool IsNormalCategoryCode(string categoryCode)
        {
            var regex = new Regex("[^-]+-\\d+");
            var match = regex.Match(categoryCode);
            return match.Success;
        }


        public override bool Execute()
        {
            log.Info("ProductCategoryProcessor.Execute()");
            log.Info("Link: " + Link.Url);
            
           

            var xmlSerializer = new XmlSerializer<ProductCategoriesConfig>();
            var config = xmlSerializer.Deserialize(LinkConfig.BuildPath());

            var ns = new NamespaceUriItem { Name = "ns", Value = "http://www.w3.org/1999/xhtml" };
            var namespaces = new ArrayList { ns };

            var linkRepo = new LinkRepository();
            var productCategoryRepo = new ProductCategoryRepository();

            try
            {
                var xmlWebPage = new XmlWebPage(new Uri(Link.Url), namespaces);
                xmlWebPage.Download();

                var categoryNodes = xmlWebPage.SelectNodes(config.ProductCategoryNode.Context);
                var nsManager = xmlWebPage.XmlNamespaceManager;
                foreach (XmlNode categoryNode in categoryNodes)
                {
                    try
                    {
                        var categoryName = config.ProductCategoryName.GetString(categoryNode, nsManager);
                        var categoryCode = config.ProductCategoryCode.GetString(categoryNode, nsManager);
                        var categoryUrl = config.ProductCategoryUrl.GetString(categoryNode, nsManager);

                        Console.WriteLine(categoryName);

                        var link = new Link { Url = categoryUrl, };
                        if (!IsNormalCategoryCode(categoryCode))
                        {
                            link.SubGenreId = Link.SubGenreId;
                            link.ProductCategoryId = Link.ProductCategoryId;                            
                        }
                        else
                        {
                            var pCategory = new ProductCategory
                            {
                                ProductCategoryName = categoryName,
                                ProductCategoryCode = categoryCode,
                                ProductCategoryURL = categoryUrl,
                                SubGenreId = Link.SubGenreId,
                            };

                            productCategoryRepo.InsertOrUpdate(pCategory);
                            productCategoryRepo.Save();

                            if (pCategory.ProductCategoryId != 0)
                                link.ProductCategoryId = pCategory.ProductCategoryId;

                            var parentNode = categoryNode.SelectSingleNode(config.ParentProductCategoryNode.Context, nsManager);
                            if (parentNode != null)
                            {
                                var parentNodeUrl = config.ProductCategoryUrl.GetString(parentNode, nsManager);
                                var parentPCategory = productCategoryRepo.Single(p => p.ProductCategoryURL == parentNodeUrl);
                                if (parentPCategory != null)
                                {
                                    pCategory.ParentProductCategoryId = parentPCategory.ProductCategoryId;
                                    productCategoryRepo.InsertOrUpdate(pCategory);
                                    productCategoryRepo.Save();
                                }
                            }
                        }

                        linkRepo.InsertOrUpdate(link);
                        linkRepo.Save();
                    }
                    catch (Exception e)
                    {
                        log.Error(string.Format("ProductCategoryProcessor - GetProductCategory Exception\nNode: {0}", categoryNode.OuterXml), e);
                    }
                }

                log.Info(string.Format("Finished - Url: {0}", Link.Url));
            }
            catch (Exception e)
            {
                log.Error(string.Format("ProductCategoryProcessor Exception"), e);
                return false;
            }
            finally
            {                
                linkRepo.Dispose();
                productCategoryRepo.Dispose();
            }

            return true;
        }
    }
}
